/**
 * 事件发射器
 * @description 支持全局和局部事件通信的基础事件管理类
 */

/**
 * 事件系统类型定义
 */

/** 事件回调函数类型 */
export type EventCallback = (...args: any[]) => void;

/** 事件处理器接口 */
export interface EventHandler {
    callback: EventCallback;
    once: boolean;
    priority: number;
}

/** 事件映射接口 */
export interface EventMap {
    [eventName: string]: EventHandler[];
}

export class EventEmitter {
    private events: EventMap = {};

    /**
     * 注册事件监听器
     * @param event 事件名称
     * @param callback 回调函数
     * @param options 配置选项
     */
    public on(event: string, callback: EventCallback, options: { once?: boolean; priority?: number } = {}) {
        const { once = false, priority = 0 } = options;

        if (!this.events[event]) {
            this.events[event] = [];
        }

        const handler: EventHandler = { callback, once, priority };

        // 根据优先级插入
        const handlers = this.events[event];
        let index = handlers.findIndex((h) => h.priority <= priority);
        if (index === -1) {
            index = handlers.length;
        }
        handlers.splice(index, 0, handler);
    }

    /**
     * 注册一次性事件监听器
     * @param event 事件名称
     * @param callback 回调函数
     * @param priority 优先级
     */
    public once(event: string, callback: EventCallback, priority: number = 0) {
        this.on(event, callback, { once: true, priority });
    }

    /**
     * 移除事件监听器
     * @param event 事件名称
     * @param callback 回调函数
     */
    public off(event: string, callback?: EventCallback) {
        if (!this.events[event]) return;

        if (callback) {
            this.events[event] = this.events[event].filter((handler) => handler.callback !== callback);
        } else {
            delete this.events[event];
        }
    }

    /**
     * 触发事件
     * @param event 事件名称
     * @param args 参数列表
     */
    public emit(event: string, ...args: any[]) {
        if (!this.events[event]) return;

        // 创建副本以避免在遍历过程中修改数组
        const handlers = [...this.events[event]];

        for (const handler of handlers) {
            handler.callback(...args);

            if (handler.once) {
                this.off(event, handler.callback);
            }
        }
    }

    /**
     * 清除所有事件监听器
     */
    public clear() {
        this.events = {};
    }
}
